﻿using System;
using System.Collections.Generic;
using System.IO;
using GeoAPI.Geometries;
using NetTopologySuite.Algorithm;
using NetTopologySuite.GeometriesGraph;

namespace NetTopologySuite.Operation.Relate
{
	public class EdgeEndBundle : EdgeEnd
	{
		public EdgeEndBundle(IBoundaryNodeRule boundaryNodeRule, EdgeEnd e) : base(e.Edge, e.Coordinate, e.DirectedCoordinate, new Label(e.Label))
		{
			this.Insert(e);
		}

		public EdgeEndBundle(EdgeEnd e) : this(null, e)
		{
		}

		public IEnumerator<EdgeEnd> GetEnumerator()
		{
			return this._edgeEnds.GetEnumerator();
		}

		public IList<EdgeEnd> EdgeEnds
		{
			get
			{
				return this._edgeEnds;
			}
		}

		public void Insert(EdgeEnd e)
		{
			this._edgeEnds.Add(e);
		}

		public override void ComputeLabel(IBoundaryNodeRule boundaryNodeRule)
		{
			bool flag = false;
			IEnumerator<EdgeEnd> enumerator = this._edgeEnds.GetEnumerator();
			{
				while (enumerator.MoveNext())
				{
					if (enumerator.Current.Label.IsArea())
					{
						flag = true;
					}
				}
			}
			if (flag)
			{
				base.Label = new Label(Location.Null, Location.Null, Location.Null);
			}
			else
			{
				base.Label = new Label(Location.Null);
			}
			for (int i = 0; i < 2; i++)
			{
				this.ComputeLabelOn(i, boundaryNodeRule);
				if (flag)
				{
					this.ComputeLabelSides(i);
				}
			}
		}

		private void ComputeLabelOn(int geomIndex, IBoundaryNodeRule boundaryNodeRule)
		{
			int num = 0;
			bool flag = false;
			Location location;
			foreach (EdgeEnd edgeEnd in this._edgeEnds)
			{
				location = edgeEnd.Label.GetLocation(geomIndex);
				if (location == Location.Boundary)
				{
					num++;
				}
				if (location == Location.Interior)
				{
					flag = true;
				}
			}
			location = Location.Null;
			if (flag)
			{
				location = Location.Interior;
			}
			if (num > 0)
			{
				location = GeometryGraph.DetermineBoundary(boundaryNodeRule, num);
			}
			base.Label.SetLocation(geomIndex, location);
		}

		private void ComputeLabelSides(int geomIndex)
		{
			this.ComputeLabelSide(geomIndex, Positions.Left);
			this.ComputeLabelSide(geomIndex, Positions.Right);
		}

		private void ComputeLabelSide(int geomIndex, Positions side)
		{
			foreach (EdgeEnd edgeEnd in this._edgeEnds)
			{
				if (edgeEnd.Label.IsArea())
				{
					Location location = edgeEnd.Label.GetLocation(geomIndex, side);
					if (location == Location.Interior)
					{
						base.Label.SetLocation(geomIndex, side, Location.Interior);
						break;
					}
					if (location == Location.Exterior)
					{
						base.Label.SetLocation(geomIndex, side, Location.Exterior);
					}
				}
			}
		}

		public void UpdateIM(IntersectionMatrix im)
		{
			Edge.UpdateIM(base.Label, im);
		}

		public override void Write(StreamWriter outstream)
		{
			outstream.WriteLine("EdgeEndBundle--> Label: " + base.Label);
			foreach (EdgeEnd edgeEnd in this._edgeEnds)
			{
				edgeEnd.Write(outstream);
				outstream.WriteLine();
			}
		}

		private readonly IList<EdgeEnd> _edgeEnds = new List<EdgeEnd>();
	}
}
